#ifndef _APPLICATION_H
#define _APPLICATION_H

#include "input/InputLayer.h"

#define LEN 8192

class cApplication {
protected:

    //==========--------------------------  Variables de Clase

    std::string m_title; // Titulo de la ventana
    int m_width; // Ancho de la ventana
    int m_height; // Alto de la ventana

    int m_red; // Cantidad de rojo (rgb)
    int m_green; // Cantidad de verde (rgb)
    int m_blue; // Cantidad de azul (rgb)
    int m_alpha; // Canal alpha

    int m_bpp; // Profundidad del color
    int m_snl; // 
    int m_mode; // Modo de la ventana (GLFW_FULLSCREEN, GLFW_WINDOW)

    bool m_bActive; // Estado activo de la app

    int m_glFlags; // Flags para GraphicsLayer
    
    static cApplication* m_pGlobalApp;
    
    virtual void InitPrimaryWindow();
    virtual void InitGraphics();
    virtual void InitInput();
    virtual void InitSound();
    virtual void InitExtraSubsystems();
    void GetFrameworkPaths();

public:
    
    static const int APP_WIDTH = 0;
    static const int APP_HEIGHT = 0;

    static const int APP_RED = 5;
    static const int APP_GREEN = 6;
    static const int APP_BLUE = 5;
    static const int APP_ALPHA = 0;

    static const int APP_DEPTH = 0;
    static const int APP_STENCIL = 0;
    static const int APP_MODE = GLFW_WINDOW; //GLFW_FULLSCREEN, GLFW_WINDOW

    // Aplicacion    
    bool m_dAppShowFps;
    std::string m_dAppRoot; // Directorio de raiz de la aplicacion
    std::string m_dAppMedia; // Directorio de datos de la aplicacion
    std::string m_dAppTextures; // Directorio de texturas de la aplicacion
    // Frame-work
    std::string m_dFrameworkRoot; // Directorio de raiz del framework
    std::string m_dFrameworkFile; // Directorio de archivos del framework
    std::string m_dFrameworkGraphics; // Directorio de graficos del framework
    std::string m_dFrameworkShaders; // Directorio de shaders del framework
    std::string m_dFrameworkWindow; // Directorio de ventana del framework
    
    cApplication();
    virtual ~cApplication();

    /**
     */
    wchar_t MediaDir();

    /**
     * Inicializacion de la App
     */
    virtual void Init();

    /**
     * Corre la App
     */
    virtual void Run();

    /**
     * Update de cada cuadro
     */
    virtual void Update(float timeDelta);

    /**
     * Renderiza cada cuadro
     * timeDelta == amount of time (in seconds) since last call
     */
    virtual void DoFrame(float timeDelta);
    virtual void DoIdleFrame(float timeDelta);


    /**
     * SceneInit se llama en Init. el usuario no debe settear D3D
     * u obtener mensajes de error.
     */
    virtual void SceneInit();
    virtual void SceneEnd();

    void Pause() {
        m_bActive = false;
    }

    void UnPause() {
        m_bActive = true;
    }

    static cApplication* GetApplication() {
        return m_pGlobalApp;
    }

    static void KillApplication() {
        delete m_pGlobalApp;
        m_pGlobalApp = NULL;
    }
    
    void printAt(int x, int y, const char* format, ...);

    double calcularFPS(double theTimeInterval, bool log);
    
};

inline cApplication* Application() {
    return cApplication::GetApplication();
}

/**
 * Funcion implementada por cualquier cliente del framework
 */
cApplication* CreateApplication(); // Devuelve un puntero valido a un obejto aplicacion

#endif // _APPLICATION_H